# @Time : 2021/5/7 13:43
# @Author : Fioman 
# @Phone : 13149920693
from tools.hd_logger import HdLogger
from vision_process.image_transfer import *
from tools.common_tools import image_to_string
from tools.send_to_ui_tools import send_cutter_camera_cal_state
import gevent
from vision_process.cutter_image_deal import *
from tools.save_image_to_device import *

"""
铡刀相机标定的相关逻辑都在这里写,铡刀标定的时候,具体想一下,如何去标定比较好.先把图片处理好,然后就是找那种.先判断是哪种情况
铡刀标定的时候的流程:
1> 1号灯管的数据
2> 2号灯管的数据
3> 3号灯管的数据
4> 4号灯关掉额数据
默认的先写几个值进去,这样搞的话数据库,会不会有点多呢.还是这么去封装.
保存的时候,保存两个值.按照顺序去排序就可以了.
标定的像素位置1,
标定的实际位置,
标定的像素位置2,
标定的实际位置2,
展示到界面上,获取到之后,肯定要排序的,位置排序,还有就是灯管排序.
如果超过了两个值呢,如何写覆盖的问题.这是一个大问题,如何覆盖掉原来的值,你知道哪个值是有效的或者无效的吗?
你不知道,你通过什么样的方式去重新标定这个位置.
灯管位置 X起点 X终点  Y起点  Y终点   点1像素坐标,点2像素坐标   点1mm坐标,点2mm坐标  像素比  灯管间距
"""

db = DbHandler()
logger = HdLogger()


class CutterCamCal(object):
    def __init__(self, cutterCam1, cutterCam2, cutterZmc):
        self.cutterCam1 = cutterCam1
        self.cutterCam2 = cutterCam2
        self.cutterZmc = cutterZmc
        self.reload_light_params()

    def reload_light_params(self):
        """
        加载灯管的参数信息,四个灯管全部分开来保存,主要搞定的事情是灯管的位置,灯管间距,像素比,还有灯管间距
        :return:
        """
        res1, light1Info = db.get_light_params(1)
        errorInfo = ""
        if res1 != "ok":
            errorInfo = "in CutterCamCal.reload_light_params() error: {}".format(light1Info)
        res2, light2Info = db.get_light_params(2)
        if res2 != "ok":
            errorInfo = "in CutterCamCal.reload_light_params() error: {}".format(light2Info)
        res3, light3Info = db.get_light_params(3)
        if res3 != "ok":
            errorInfo = "in CutterCamCal.reload_light_params() error: {}".format(light3Info)
        res4, light4Info = db.get_light_params(4)
        if res4 != "ok":
            errorInfo = "in CutterCamCal.reload_light_params() error: {}".format(light4Info)

        if errorInfo != "":
            print(errorInfo)
            logger.debug(errorInfo)
        else:
            # 将数据提取出来
            getDataError = ""
            self.light1Pos = [light1Info.get("xStart"), light1Info.get("xEnd"), light1Info.get("yStart"), light1Info.get("yEnd")]
            self.light2Pos = [light2Info.get("xStart"), light2Info.get("xEnd"), light2Info.get("yStart"), light2Info.get("yEnd")]
            self.light3Pos = [light3Info.get("xStart"), light3Info.get("xEnd"), light3Info.get("yStart"), light3Info.get("yEnd")]
            self.light4Pos = [light4Info.get("xStart"), light4Info.get("xEnd"), light4Info.get("yStart"), light4Info.get("yEnd")]
            if None in light1Info:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light1Params灯管位置获取为None")
            if None in light2Info:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light2Params灯管位置获取为None")
            if None in light3Info:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light3Params灯管位置获取为None")
            if None in light4Info:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light4Params灯管位置获取为None")

            # 获取灯管的间距,还有像素比
            self.ruler1MmToPix = light1Info.get("mmToPix")
            self.ruler2MmToPix = light2Info.get("mmToPix")
            self.ruler3MmToPix = light3Info.get("mmToPix")
            self.ruler4MmToPix = light4Info.get("mmToPix")
            if self.ruler1MmToPix is None:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light1Params的mmToPix获取为None")
            if self.ruler2MmToPix is None:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light2Params的mmToPix获取为None")
            if self.ruler3MmToPix is None:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light3Params的mmToPix获取为None")
            if self.ruler4MmToPix is None:
                getDataError += "in CutterCamCal.reload_light_params() error: {}".format("light4Params的mmToPix获取为None")

            # 获取灯管间距
            self.lightOffset1And2 = light1Info.get("lightBtween12")
            self.lightOffset3And4 = light3Info.get("lightBtween34")

            # 获取标定的位置像素点和实际距离点
            light1Pos1Pix = light1Info.get("pos1Pix")
            light1Pos1Mm = light1Info.get("pos1Mm")
            light2Pos1Pix = light2Info.get("pos1Pix")
            light2Pos1Mm = light2Info.get("pos1Mm")
            light3Pos1Pix = light3Info.get("pos1Pix")
            light3Pos1Mm = light3Info.get("pos1Mm")
            light4Pos1Pix = light4Info.get("pos1Pix")
            light4Pos1Mm = light4Info.get("pos1Mm")

            self.ruler1 = [light1Pos1Pix, light1Pos1Mm, self.ruler1MmToPix]  # 1号尺子信息
            self.ruler2 = [light2Pos1Pix, light2Pos1Mm, self.ruler2MmToPix]  # 2号尺子信息
            self.ruler3 = [light3Pos1Pix, light3Pos1Mm, self.ruler3MmToPix]  # 3号尺子信息
            self.ruler4 = [light4Pos1Pix, light4Pos1Mm, self.ruler4MmToPix]  # 4号尺子信息

    @staticmethod
    def web_request_get_light_params():
        """
        前端界面请求更新前端界面上的铡刀灯管的参数信息
        :return:
        """
        lightParamsList = []
        for i in range(1, 5):
            res, lightParams = db.get_light_params(i)
            if res != "ok":
                errorInfo = lightParams
                print(errorInfo)
                logger.debug(errorInfo)
            else:
                lightParamsList.append([lightParams])
        if len(lightParamsList) > 0:
            return lightParamsList
        else:
            return [None, None, None, None]

    @staticmethod
    def get_cutter_image_without_camera_for_test(camNumber):
        """
        获取铡刀的图片,测试的时候使用,这个时候相机获取不到图片,只能自己测试搞一张图片
        :param camNumber 相机编号,1和2,1代表1号相机,2代表2号相机
        :return: 返回模拟相机拍照拿到的图片
        """
        if camNumber == 1:
            image = cv.imread(r"D:\shenghong\cutter_raw\8602--time2021-05-08_01-53-25--begin_angle_fail.bmp", cv.IMREAD_GRAYSCALE)
        else:
            image = cv.imread(r"D:\shenghong\cutter_raw\8604--time2021-05-08_01-54-14--end--cam2.bmp", cv.IMREAD_GRAYSCALE)

        return image

    def web_request_cutter_down(self, downDis):
        """
        前端界面点击了铡刀下降按钮
        :param downDis: 移动的距离
        :return:
        """
        logger.debug("前端界面点击了铡刀下降按钮,执行下降动作,下降的距离: {}".format(downDis))
        ret, info = self.cutterZmc.move_cutter_knife(float(downDis))
        return "ok" if ret == 0 else info

    def web_request_check_light_pos(self, lightNum):
        """
        前端界面请求获取灯管的位置参数信息是否正确,来进行验证.
        :param lightNum: 灯管的编号
        :return:
        """
        if lightNum == 1:
            lightPos = self.light1Pos
        elif lightNum == 2:
            lightPos = self.light2Pos
        elif lightNum == 3:
            lightPos = self.light3Pos
        else:
            lightPos = self.light4Pos
        # 如果是正常状态下,是否是在设备的调试模式下进行的
        if lightNum == 1 or lightNum == 2:
            camNum = 1
        else:
            camNum = 2
        testWithoutCamera = False  # 是否是在测试模式下
        if testWithoutCamera:
            image = self.get_cutter_image_without_camera_for_test(camNum)
        else:
            # 先开灯,然后再去获取图片
            if camNum == 1:
                self.cutterZmc.open_cutter_cam1_light_source()
            else:
                self.cutterZmc.open_cutter_cam2_light_source()
            gevent.sleep(2)
            res, image = self.get_cutter_image(camNum)
            if camNum == 1:
                self.cutterZmc.close_cutter_cam1_light_source()
            else:
                self.cutterZmc.close_cutter_cam2_light_source()

        # 然后就是在铡刀的图片上进行画线,并且写入字体,返回给前端
        retImage = self.put_light_pos_info_to_image(image, lightPos)
        save_cutter_cam_cal_image(camNum, image, "light_{}_pos_original".format(lightNum))
        save_cutter_cam_cal_image(camNum, retImage, "light_{}_pos_res".format(lightNum))
        imageSend = image_to_string(retImage)
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": "注意: 1) 确保灯管的选取尽量的长,y轴尽量居中,取50个像素  2) 1和2号灯管的xStart在图像的右侧  3) 3和4号灯管的xStart在图像的左侧"
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def get_cutter_image(self, camNum):
        """
        根据相机编号获取铡刀的图片
        :param camNum: 相机的编号
        :return:
        """
        try:
            if camNum == 1:
                cutterCam = self.cutterCam1
            elif camNum == 2:
                cutterCam = self.cutterCam2
            else:
                return "相机编号错误,只能是1和2", None
            isDeviceOnLine = cutterCam.is_device_online()
            if not isDeviceOnLine:
                return "相机不在线,请确认相机已经正确的连接上", None
            cutterCam.start_grabbing()
            ret, image = cutterCam.get_image()
            if ret != 0:
                for i in range(5):
                    ret, image = cutterCam.get_image()
                    if ret != 0:
                        continue
                    else:
                        # 二号相机需要X，Y同时翻转
                        if camNum == 1:
                            rotateImage = flip_image(image, "XY")
                        else:
                            rotateImage = image.copy()

                        if camNum == 1:
                            cv.putText(rotateImage, "1", (1500, 720), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                            cv.putText(rotateImage, "2", (1500, 1900), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                        else:
                            cv.putText(rotateImage, "3", (1500, 720), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                            cv.putText(rotateImage, "4", (1500, 1600), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                        return "ok", rotateImage
                else:
                    errorInfo = "铡刀{}号相机拍照失败,重新拍照了10次都失败!".format(camNum)
                    print(errorInfo)
                    logger.debug(errorInfo)
                    return errorInfo, None
            else:
                # 二号相机需要X，Y同时翻转
                if camNum == 1:
                    rotateImage = flip_image(image, "XY")
                else:
                    rotateImage = image.copy()
                if camNum == 1:
                    cv.putText(rotateImage, "1", (1500, 720), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                    cv.putText(rotateImage, "2", (1500, 1900), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                else:
                    cv.putText(rotateImage, "3", (1500, 720), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                    cv.putText(rotateImage, "4", (1500, 1600), cv.FONT_HERSHEY_COMPLEX, 8, (255, 0, 0))
                return "ok", rotateImage

        except Exception as e:
            errorInfo = "in CutterCamCal.get_cutter_image() error: {}".format(str(e))
            print(errorInfo)
            logger.debug(errorInfo)
            return errorInfo, None
        finally:
            cutterCam.stop_grabbing()

    @staticmethod
    def put_light_pos_info_to_image(image, lightPos):
        """
        根据图片和位置信息,将图片的内容写上去.
        :param image: 铡刀的图片
        :param lightPos: 灯管的位置信息
        :return: 返回新的标定了位置的结果图片
        """
        imageColor = cv.cvtColor(image, cv.COLOR_GRAY2BGR)
        lightPos = [int(x) for x in lightPos]
        xStart, xEnd, yStart, yEnd = lightPos
        # 四个点的坐标分别是.
        p1 = [xStart, yStart]
        p2 = [xStart, yEnd]
        p3 = [xEnd, yEnd]
        p4 = [xEnd, yStart]
        drawPoints = [p1, p2, p3, p4]

        cv.drawContours(imageColor, [np.array(drawPoints)], -1, (0, 255, 0), 5)
        cv.putText(imageColor, "xStart", (xStart + 10, yEnd + 50), cv.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1)
        cv.putText(imageColor, "xEnd", (xEnd - 100, yEnd + 50), cv.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1)
        cv.putText(imageColor, "yStart", ((xStart + xEnd) // 2, yStart - 30), cv.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1)
        cv.putText(imageColor, "yEnd", ((xStart + xEnd) // 2, yEnd + 30), cv.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1)
        return imageColor

    def web_request_save_light_params(self, webPayload):
        """
        前端界面请求保存灯管参数的按钮被点击
        :param webPayload:前端界面传递过来的参数,包括灯管的编号,还有要保存的值
        :return:
        """
        lightNum, newData = webPayload
        res, info = db.save_light_params(lightNum, newData)
        # 然后是计算灯管间距和像素比,然后保存到新的数据库中去
        res = self.save_mmtopix_and_light_offset(lightNum)
        self.reload_light_params()
        return "ok" if res == "ok" else info

    @staticmethod
    def save_mmtopix_and_light_offset(lightNum):
        """
        保存像素比和灯管间距,这里就是重新计算一下灯管的相似比和灯管的间距并保存到数据库
        :param lightNum:灯管的编号
        :return:
        """
        if lightNum == 1 or lightNum == 2:
            light1Params = db.get_light_params(1)[1]
            light2Params = db.get_light_params(2)[1]
            # 获取1号灯管的像素比
            p1Pix = light1Params.get("pos1Pix")
            p2Pix = light1Params.get("pos2Pix")
            p1Mm = light1Params.get("pos1Mm")
            p2Mm = light1Params.get("pos2Mm")
            newMmToPix1 = round(abs(p1Pix - p2Pix) / abs(p1Mm - p2Mm), 4)

            p1Pix = light2Params.get("pos1Pix")
            p2Pix = light2Params.get("pos2Pix")
            p1Mm = light2Params.get("pos1Mm")
            p2Mm = light2Params.get("pos2Mm")
            newMmToPix2 = round(abs(p1Pix - p2Pix) / abs(p1Mm - p2Mm), 4)

            yStart1 = light1Params.get("yStart")
            yEnd1 = light1Params.get("yEnd")
            yStart2 = light2Params.get("yStart")
            yEnd2 = light2Params.get("yEnd")

            mmToPixAver = round((newMmToPix1 + newMmToPix2) / 2, 4)
            offsetPix = abs((yStart1 + yEnd1) / 2 - (yStart2 + yEnd2) / 2)
            lightOffset12 = round(offsetPix / mmToPixAver, 4)

            # 然后组件新的值,并保存到数据库中
            newData1 = {
                "mmToPix": newMmToPix1,
                "lightBtween12": lightOffset12
            }
            newData2 = {
                "mmToPix": newMmToPix2,
                "lightBtween12": lightOffset12
            }
            res, info = db.save_light_params(1, newData1)
            if res != "ok":
                return info
            res, info = db.save_light_params(2, newData2)
            return "ok" if res == "ok" else info

        else:
            light3Params = db.get_light_params(3)[1]
            light4Params = db.get_light_params(4)[1]
            # 获取1号灯管的像素比
            p1Pix = light3Params.get("pos1Pix")
            p2Pix = light3Params.get("pos2Pix")
            p1Mm = light3Params.get("pos1Mm")
            p2Mm = light3Params.get("pos2Mm")
            newMmToPix3 = round(abs(p1Pix - p2Pix) / abs(p1Mm - p2Mm), 4)

            p1Pix = light4Params.get("pos1Pix")
            p2Pix = light4Params.get("pos2Pix")
            p1Mm = light4Params.get("pos1Mm")
            p2Mm = light4Params.get("pos2Mm")
            newMmToPix4 = round(abs(p1Pix - p2Pix) / abs(p1Mm - p2Mm), 4)

            yStart3 = light3Params.get("yStart")
            yEnd3 = light3Params.get("yEnd")
            yStart4 = light4Params.get("yStart")
            yEnd4 = light4Params.get("yEnd")

            mmToPixAver = round((newMmToPix3 + newMmToPix4) / 2, 4)
            offsetPix = abs((yStart3 + yEnd3) / 2 - (yStart4 + yEnd4) / 2)
            lightOffset34 = round(offsetPix / mmToPixAver, 4)

            # 然后组件新的值,并保存到数据库中
            newData3 = {
                "mmToPix": newMmToPix3,
                "lightBtween34": lightOffset34
            }
            newData4 = {
                "mmToPix": newMmToPix4,
                "lightBtween34": lightOffset34
            }
            res, info = db.save_light_params(3, newData3)
            if res != "ok":
                return info
            res, info = db.save_light_params(4, newData4)
            return "ok" if res == "ok" else info

    def web_request_cal_cutter_cam2(self, calInfo):
        """
        前端界面上点击了标定2号相机的按钮
        :param calInfo: 标定的信息,位置编号,以及标定的位置信息
        :return:
        """
        camNum = 2  # 2号相机的标定
        posNum, posDis = calInfo
        posNum = int(posNum)
        posDis = float(posDis)
        if posDis == "":
            return "标定的位置不能是空,请正切填写标定位置"

        # 1.先打开光源
        self.cutterZmc.open_cutter_cam2_light_source()
        gevent.sleep(1)  # 休眠秒,等待光源完全打开
        # 2> 先去获取图片
        res, image = self.get_cutter_image(camNum)
        self.cutterZmc.close_cutter_cam2_light_source()
        if res != "ok":
            return res
        # 3> 图片获取成功以后,去识别这里的位置,然后进行标定
        light3CalPix, light4CalPix, imageRes = get_first_thres_point_final_check_cam_2(image, self.light3Pos, self.light4Pos)
        hintInfo = "3号灯管: pix={},mm={}, 4号灯管: pix={},mm={}".format(light3CalPix, posDis, light4CalPix, posDis)
        imageSend = image_to_string(imageRes)
        keepIndex = 2
        # 4> 保存原图和结果图片
        save_cutter_cam_cal_image(keepIndex, image)
        save_cutter_cam_cal_image(keepIndex, imageRes, endWith="res")
        # 5> 保存进数据库,同时标定的是两个灯管的位置
        if posNum == 1:
            newData1 = {
                "pos1Pix": light3CalPix,
                "pos1Mm": posDis
            }
            newData2 = {
                "pos1Pix": light4CalPix,
                "pos1Mm": posDis
            }
        else:
            newData1 = {
                "pos2Pix": light3CalPix,
                "pos2Mm": posDis
            }
            newData2 = {
                "pos2Pix": light4CalPix,
                "pos2Mm": posDis
            }
        res, info = db.save_light_params(3, newData1)
        if res != "ok":
            return info
        res, info = db.save_light_params(4, newData2)
        if res != "ok":
            return info
        # 保存完之后,再重新计算一次灯管间距以及像素比,并且重新刷新一次参数.
        self.save_mmtopix_and_light_offset(3)
        self.reload_light_params()
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_cal_cutter_cam1(self, calInfo):
        """
        前端界面点击了标定1号相机的按钮
        :param calInfo: 标定的信息,位置编号,以及标定的位置信息
        :return:
        """
        camNum = 1  # 1号相机的标定
        posNum, posDis = calInfo
        posDis = float(posDis)
        if posDis == "":
            return "标定的位置不能是空,请正切填写标定位置"

        # 1.先打开光源
        self.cutterZmc.open_cutter_cam1_light_source()
        gevent.sleep(1)  # 休眠秒,等待光源完全打开
        # 2> 先去获取图片
        res, image = self.get_cutter_image(camNum)
        if res != "ok":
            return res
        # 3> 图片获取成功以后,去识别这里的位置,然后进行标定
        light1CalPix, light2CalPix, imageRes = get_first_thres_point_final_check_cam_1(image, self.light1Pos, self.light2Pos)
        hintInfo = "1号灯管: pix={},mm={}, 2号灯管: pix={},mm={}".format(light1CalPix, posDis, light2CalPix, posDis)
        imageSend = image_to_string(imageRes)
        keepIndex = 1
        # 4> 保存原图和结果图片
        self.cutterZmc.close_cutter_cam1_light_source()
        save_cutter_cam_cal_image(keepIndex, image)
        save_cutter_cam_cal_image(keepIndex, imageRes, endWith="res")
        # 5> 保存进数据库,同时标定的是两个灯管的位置
        if posNum == 1:
            newData1 = {
                "pos1Pix": light1CalPix,
                "pos1Mm": posDis
            }
            newData2 = {
                "pos1Pix": light2CalPix,
                "pos1Mm": posDis
            }
        else:
            newData1 = {
                "pos2Pix": light1CalPix,
                "pos2Mm": posDis
            }
            newData2 = {
                "pos2Pix": light2CalPix,
                "pos2Mm": posDis
            }
        res, info = db.save_light_params(1, newData1)
        if res != "ok":
            return info
        res, info = db.save_light_params(2, newData2)
        if res != "ok":
            return info
        # 保存完之后,再重新计算一次灯管间距以及像素比,并且重新刷新一次参数.
        self.save_mmtopix_and_light_offset(1)
        self.reload_light_params()
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_verify_cutter_cam1_cal(self):
        """
        界面上点击了铡刀1号相机验证,这里就是要根据第一个点去计算了.
        :return:
        """
        # 1.先开灯
        self.cutterZmc.open_cutter_cam1_light_source()
        gevent.sleep(1)
        # 2.获取图片
        camNum = 1
        res, image = self.get_cutter_image(camNum)
        self.cutterZmc.close_cutter_cam1_light_source()
        if res != "ok":
            return res
        # 3.获取在尺子上的位置
        firstThres1, firstThres2, cam1ImageRes = get_first_thres_point_final_check_cam_1(image, self.light1Pos, self.light2Pos)
        toCutterMm1, toCutterMm2, checkAngle = self.get_offset_to_cutter_by_ruler(camNum, firstThres1, firstThres2)
        hintInfo = "1号灯管: mm = {}, 2号灯管: mm = {}, 角度 = {}".format(toCutterMm1, toCutterMm2, checkAngle)
        imageSend = image_to_string(cam1ImageRes)
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_verify_cutter_cam2_cal(self):
        """
        前端界面上点击了2号相机标定验证的逻辑
        :return:
        """
        self.cutterZmc.open_cutter_cam2_light_source()
        gevent.sleep(1)
        # 2.获取图片
        camNum = 2
        res, image = self.get_cutter_image(camNum)
        self.cutterZmc.close_cutter_cam2_light_source()
        if res != "ok":
            return res
        # 3.获取在尺子上的位置
        firstThres1, firstThres2, cam1ImageRes = get_first_thres_point_final_check_cam_2(image, self.light3Pos, self.light4Pos)
        toCutterMm1, toCutterMm2, checkAngle = self.get_offset_to_cutter_by_ruler(camNum, firstThres1, firstThres2)
        hintInfo = "3号灯管: {}, 4号灯管: {}, 角度 = {}".format(toCutterMm1, toCutterMm2, checkAngle)
        imageSend = image_to_string(cam1ImageRes)
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_verify_cutter_cam_total(self):
        """
        界面上点击了验证总板长.
        :return:
        """
        self.cutterZmc.open_cutter_cam1_light_source()
        self.cutterZmc.open_cutter_cam2_light_source()
        gevent.sleep(1)
        res1, image1 = self.get_cutter_image(1)
        res2, image2 = self.get_cutter_image(2)
        if res1 != "ok":
            return res1
        if res2 != "ok":
            return res2
        self.cutterZmc.close_cutter_cam1_light_source()
        self.cutterZmc.close_cutter_cam2_light_source()
        firstThres1, firstThres2, cam1ImageRes = get_first_thres_point_final_check_cam_1(image1, self.light1Pos, self.light2Pos)
        toCutterMm1, toCutterMm2, checkAngle = self.get_offset_to_cutter_by_ruler(1, firstThres1, firstThres2)
        secondBoardLen = round((toCutterMm1 + toCutterMm2) / 2, 2)
        hintInfo1 = "1号灯管: {}, 2号灯管: {},第二块 = {}, 角度 = {},".format(toCutterMm1, toCutterMm2, secondBoardLen, checkAngle)
        firstThres3, firstThres4, cam2ImageRes = get_first_thres_point_final_check_cam_2(image2, self.light3Pos, self.light4Pos)
        toCutterMm3, toCutterMm4, checkAngle = self.get_offset_to_cutter_by_ruler(2, firstThres3, firstThres4)
        firstBoardLen = round((toCutterMm3 + toCutterMm4) / 2, 2)
        totalBoardLen = round((firstBoardLen + secondBoardLen), 2)
        hintInfo2 = "3号灯管: {}, 4号灯管: {},第一块 = {}, 角度 = {},总板长 = {}".format(toCutterMm4, toCutterMm4, firstBoardLen,
                                                                           checkAngle, totalBoardLen)
        jointImage = np.hstack((cam1ImageRes, cam2ImageRes))
        imageSend = image_to_string(jointImage)
        hintInfo = hintInfo1 + hintInfo2
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_verify_cutter_begin_check(self):
        """
        铡刀起点检测验证按钮被点击
        :return:
        """
        # 1.先开灯
        self.cutterZmc.open_cutter_cam1_light_source()
        gevent.sleep(1)
        # 2.获取图片
        camNum = 1
        res, image = self.get_cutter_image(camNum)
        self.cutterZmc.close_cutter_cam1_light_source()
        if res != "ok":
            return res
        # 3.获取在尺子上的位置
        firstThres1, firstThres2, cam1ImageRes = get_first_thres_point_begain_check(image, self.light1Pos, self.light2Pos)
        toCutterMm1, toCutterMm2, checkAngle = self.get_offset_to_cutter_by_ruler(camNum, firstThres1, firstThres2)
        save_cutter_cam_cal_image(1, image, endWith="begin_check_original")
        save_cutter_cam_cal_image(1, cam1ImageRes, endWith="begin_check_res")
        hintInfo = "1号灯管: mm = {}, 2号灯管: mm = {}, 角度 = {}".format(toCutterMm1, toCutterMm2, checkAngle)
        imageSend = image_to_string(cam1ImageRes)
        msgValue = {
            "val": "updateCutterCalImage",
            "cutterCalImage": imageSend,
            "hintInfo": hintInfo
        }
        send_cutter_camera_cal_state(msgValue)
        return "ok"

    def web_request_open_cutter_cam_cal_dir(self):
        """
        打开铡刀标定的文件目录
        :return:
        """
        return open_cutter_cam_cal_dir()

    def get_offset_to_cutter_by_ruler(self, camNum, firstThres1, firstThres2):
        """
        根据相机的编号以及找到在尺子上的像素点,获取它到铡刀的mm距离
        :param camNum: 相机编号
        :param firstThres1: 1号或者3号灯管的找到的位置
        :param firstThres2: 2号或者4号灯管找到的像素位置
        :return:
        """
        if camNum == 1:
            ruler1 = self.ruler1
            ruler2 = self.ruler2
            lightOffset = self.lightOffset1And2
        else:
            ruler1 = self.ruler3
            ruler2 = self.ruler4
            lightOffset = self.lightOffset3And4

        # 1.先将尺子上的内容选取出来
        pix1, mm1, mmToPix1 = ruler1
        pix2, mm2, mmToPix2 = ruler2
        newMm1 = mm1 + (firstThres1 - pix1) / mmToPix1
        newMm2 = mm2 + (firstThres2 - pix2) / mmToPix2
        checkAngleTan = (newMm2 - newMm1) / lightOffset  # 要确保计算的角度是正值的时候,逆时针旋转
        checkAngle = round(np.arctan(checkAngleTan) * (180 / np.pi), 2)
        if camNum == 2:
            checkAngle = -checkAngle
        return round(newMm1, 2), round(newMm2, 2), checkAngle

    def web_request_delete_total_cutter_cal_image(self):
        """
        界面上点击了删除所有的标定用图片
        :return:
        """
        return delete_total_cutter_cal_image()


if __name__ == '__main__':
    pass
